//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//
// (C) Copyright 2006 Marvell International Ltd.
// All Rights Reserved
//
#include <windows.h>
#include <iplcommon.h>
#include <bootpart.h>   // Needed for partition types...
#include <bsp.h>


#include "xllp_pm.h"
#include "xllp_pm_dvfm.h"
#include "monahans_base_regs.h"
#include "xllp_defs.h"
#include "xllp_udc.h"
#include "xllp_lcd_plat.h"
#include "xllp_pm_Micco.h"
#include "xllp_i2c.h"
#include "xllp_mfp_proc.h"

#define ON TRUE
#define OFF FALSE

///////////////////////////////////////////////////////////////////////////////
// Required OEM IPL routines.
///////////////////////////////////////////////////////////////////////////////
#define PMIC_STATUS 					0x04
#define PMIC_BATTERY_CHARGER_CTRL		0x28
#define PMIC_BATTERY_CCTR_CTRL			0x29
#define PMIC_BATTERY_TCTR_CTRL			0x2A
#define PMIC_BATTERY_CHARG_PULSE		0x2B
#define PMIC_ADC_MAN_CTRL				0x30
#define PMIC_ADC_VBATMON				0x32
#define PMIC_ADC_VBATMONTXON			0x33
#define PMIC_ADC_MAN_RES				0x40

#define CHARGER_VOLTAGE_4_2V    0x4
#define CHARGER_ENABLE			(0x1 << 7)
#define CHARGER_DISABLE			(0x0 << 7)

#define VBAT_ADC_HIGH	120 // ~410 mV

#define CHARGER_VOLTAGE_4_2V    0x4

static XLLP_VUINT32_T *g_pOST;
static XLLP_VUINT32_T *g_pI2C;
static XLLP_VUINT32_T *g_pMFP;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
static I2CInit()
{
    char pMfpRMDb[XLLP_MFP_RM_DB_SIZE];

	if (XLLP_STATUS_SUCCESS!=XllpMfpResourceManagerInit(pMfpRMDb))
	{
		EdbgOutputDebugString("[XllpMfpResourceManagerInit() failed!\r\n");
	}

	if(XLLP_STATUS_SUCCESS!=XllpI2cInit((P_XLLP_I2C_T)g_pI2C, (P_XLLP_VUINT32_T) g_pMFP, (P_XLLP_MFP_RM_DB_ID_T )pMfpRMDb, 0))
	{
		EdbgOutputDebugString("[XllpI2cInit() failed!\r\n");
	}
}


//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
static BOOL Read(BYTE Reg, BYTE *pVal)
{
    XLLP_UINT8_T buf[2];
    XLLP_STATUS_T ret;


	ret=XllpPmMiccoRead((P_XLLP_I2C_T) g_pI2C, (XLLP_OST_T *)g_pOST, Reg, buf);

	if (XLLP_STATUS_SUCCESS == ret)
	{
		*pVal = buf[0];
		return TRUE;
	}
	else
	{
		EdbgOutputDebugString("XllpPmMiccoRead() failed - 0x%x\r\n", (unsigned int) ret);
		return FALSE;
	}
}


//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
static BOOL Write(BYTE Reg, BYTE Val)
{
    XLLP_UINT8_T buf[2];
    XLLP_STATUS_T ret;

	buf[0]=Val;
	ret=XllpPmMiccoWrite ((P_XLLP_I2C_T) g_pI2C, (XLLP_OST_T *)g_pOST, Reg, buf[0]);

	if (XLLP_STATUS_SUCCESS == ret)
		return TRUE;
	else
	{
		EdbgOutputDebugString("XllpPmMiccoRead() failed - 0x%x\r\n", (unsigned int) ret);
		return FALSE;
	}
}



//=====================================================================
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
static DWORD GetVBAT()
{
BYTE VBAT;

	Write(PMIC_ADC_MAN_CTRL, 0x10);
	Write(PMIC_ADC_MAN_CTRL, 0x18);
	Read(PMIC_ADC_MAN_RES, &VBAT);

	EdbgOutputDebugString("GetVBAT() returning: %d\r\n", VBAT);

	return VBAT;
}


//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
static BOOL IsChargerPresent(BOOL *pbAC, BOOL *pbUSB)
{
BOOL retval = FALSE;
BYTE StatusReg = 0;

	retval = Read(PMIC_STATUS, &StatusReg);

	*pbUSB = (BOOL)(StatusReg & 0x04);	// Is EXTON bit set
	*pbAC = (BOOL)(StatusReg & 0x08);	// Is CHGDET bit set

	EdbgOutputDebugString("AC Charger %s present;  USB Charger %s present.\r\n",
		(*pbAC ? "is" : "is NOT"),
		(*pbUSB ? "is" : "is NOT")
		);

	return (*pbAC || *pbUSB);
}


//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
static void SetCharger(BOOL bEnable, DWORD dwCurrent, DWORD dwVoltage)
{
	BYTE reg = 0;

	if (bEnable)
	{
		reg = (CHARGER_ENABLE | ((BYTE)(dwCurrent / 100) << 3) | (BYTE)dwVoltage);
	}
	else
	{
		reg = CHARGER_DISABLE;
	}

	Write(PMIC_BATTERY_CHARGER_CTRL, reg);

	EdbgOutputDebugString("Battery charger is %s! - %d mA\r\n", (bEnable ? "ON" : "OFF"), dwCurrent);
}


//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
BOOL EnableBatteryCharger(
    XLLP_VUINT32_T *pOST, 
    XLLP_VUINT32_T *pI2C, 
    XLLP_VUINT32_T *pMFP
    )
{
    DWORD VBAT;
    BOOL bACChargerPresent = FALSE;
    BOOL bUSBChargerPresent = FALSE;

    g_pOST = pOST;
    g_pI2C = pI2C;
    g_pMFP = pMFP;

    EdbgOutputDebugString("EnableBatteryCharger() called...\r\n");

    I2CInit();

	VBAT = GetVBAT();

	if (IsChargerPresent(&bACChargerPresent, &bUSBChargerPresent))
	{
        if ( VBAT < VBAT_ADC_HIGH )
		{
			if (bACChargerPresent)
			{
				SetCharger(ON, 700, CHARGER_VOLTAGE_4_2V);
			}
			else // bUSBChargerPresent
			{
				SetCharger(ON, 500, CHARGER_VOLTAGE_4_2V);
			}
		}		
		else // VBAT_ADC_HIGH <= VBAT
		{
			if (bACChargerPresent)
			{
				EdbgOutputDebugString("No Battery Detected.\r\n");
			}
			else // bUSBChargerPresent == TRUE
			{
				EdbgOutputDebugString("Battery is fully charged.\r\n");
				SetCharger(ON, 100, CHARGER_VOLTAGE_4_2V);
			}
			return TRUE;
		}
	}
	else
	{
		EdbgOutputDebugString("No Charger detected.\r\n");
	}

	return TRUE;
}
